#include "http_weather.h"
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "esp_log.h"
#include "esp_http_client.h"
#include <string.h>
#include "cJSON.h"   //cJSON库
#include "PipeLine.h"

// 定义最大HTTP输出缓冲区大小
#define MAX_HTTP_OUTPUT_BUFFER 512

// 初始化HTTP输出缓冲区
char output_buffer[MAX_HTTP_OUTPUT_BUFFER] = {0};
// 定义日志标签
static const char *TAG = "HTTP_WEATHER";

// 定义WeatherInfo天气变量
WeatherInfo Intimate_weather;

WeatherInfo parse_weather_json(const char *json_data) {
    WeatherInfo weather = {0};
    // 解析JSON数据，返回一个cJSON对象
    cJSON *root = cJSON_Parse(json_data);
    if (root == NULL) 
    {
        // 如果解析失败，获取错误指针
        const char *error_ptr = cJSON_GetErrorPtr();
        if (error_ptr != NULL) 
        {
            ESP_LOGE(TAG, "Error before: %s", error_ptr);
        }
        return weather;
    }

    // 从JSON对象中获取名为"results"的项
    cJSON *results = cJSON_GetObjectItem(root, "results");
    // 检查获取的results是否为NULL或者不是一个数组
    if (results == NULL || !cJSON_IsArray(results)) {
        ESP_LOGE(TAG, "Failed to get 'results' array");
        // 释放root对象占用的内存，避免内存泄漏
        cJSON_Delete(root);
        return weather;
    }

    // 从results数组中获取第一个元素，并将其指针赋值给result变量
    cJSON *result = cJSON_GetArrayItem(results, 0);
    if (result == NULL) {
        ESP_LOGE(TAG, "Failed to get first result");
        cJSON_Delete(root);
        return weather;
    }
    // 从result对象中获取名为"location"的子对象，并将其指针赋值给location变量
    cJSON *location = cJSON_GetObjectItem(result, "location");
    // 从result对象中获取名为"now"的子对象，并将其指针赋值给now变量
    cJSON *now = cJSON_GetObjectItem(result, "now");

    if (location == NULL || now == NULL) {
        ESP_LOGE(TAG, "Failed to get 'location' or 'now'");
        cJSON_Delete(root);
        return weather;
    }

    // 从location对象中获取名为"name"的子对象，并将其指针赋值给name变量
    cJSON *name = cJSON_GetObjectItem(location, "name");
    // 从now对象中获取名为"text"的子对象，并将其指针赋值给text变量
    cJSON *text = cJSON_GetObjectItem(now, "text");
    // 从now对象中获取名为"temperature"的子对象，并将其指针赋值给temperature变量
    cJSON *temperature = cJSON_GetObjectItem(now, "temperature");
    // 从result对象中获取名为"last_update"的子对象，并将其指针赋值给last_update变量
    cJSON *last_update = cJSON_GetObjectItem(result, "last_update");

    if (name == NULL || text == NULL || temperature == NULL || last_update == NULL) {
        ESP_LOGE(TAG, "Failed to get required fields");
        cJSON_Delete(root);
        return weather;
    }

    char temp_str[10] = {0};
    strncpy(temp_str, cJSON_GetStringValue(temperature), sizeof(temp_str));
    // 从JSON中获取位置名称并复制到weather结构体中的location_name
    strncpy(weather.location_name, cJSON_GetStringValue(name), sizeof(weather.location_name));
    // 从JSON中获取天气描述文本并复制到weather结构体中的weather_text
    strncpy(weather.weather_text, cJSON_GetStringValue(text), sizeof(weather.weather_text));
    // 将温度字符串转换为整数并赋值给weather结构体中的temperature
    // atoi为C库函数，可以将字符串转化为整数
    weather.temperature = atoi(temp_str);
    strncpy(weather.last_update, cJSON_GetStringValue(last_update), sizeof(weather.last_update));

    cJSON_Delete(root);
    return weather;
}

// 定义 http_test_task 函数，该任务用于通过HTTP请求获取天气信息
void http_test_task(void *pvParameters)
{
    bool success = true;

    xEventGroupWaitBits(xEventGroup, WIFI_CONNECTED_BIT, pdFALSE, pdFALSE, portMAX_DELAY);

    vTaskDelay(pdMS_TO_TICKS(13000));

    printf("Weather done\n");

    // 配置HTTP客户端参数
    esp_http_client_config_t config = {
        .url = "******", // 请求的URL地址
        .method = HTTP_METHOD_GET, // 使用GET方法请求数据
        .timeout_ms = 5000, // 设置连接超时时间为5秒
        .buffer_size = 1024 // 设置读取缓冲区大小为1024字节
    };

    // 初始化HTTP客户端
    esp_http_client_handle_t client = esp_http_client_init(&config);

    // 无限循环，持续请求天气信息
    while (1)
    {
        success = true;
        // 打开HTTP连接，0表示不设置额外的请求头
        esp_err_t err = esp_http_client_open(client, 0);
        // 检查是否成功打开连接
        if (err != ESP_OK)
        {
            // 如果连接失败，记录错误日志。
            ESP_LOGE(TAG, "Failed to open HTTP connection: %s", esp_err_to_name(err));
            success = false;
            goto http_cleanup;
        }

        // 获取HTTP响应的头部信息，返回响应内容长度
        // 这个函数会尝试从HTTP服务器读取响应的头部，并返回响应内容的长度。
        int content_length = esp_http_client_fetch_headers(client);
        // 检查是否成功获取头部信息
        if (content_length < 0)
        {
            // 如果获取头部信息失败，记录错误日志。
            ESP_LOGE(TAG, "HTTP client fetch headers failed");
            esp_http_client_close(client);
            success = false;
            goto http_cleanup;
        }

        // 读取HTTP响应数据到输出缓冲区
        int data_read = esp_http_client_read_response(client, output_buffer, MAX_HTTP_OUTPUT_BUFFER);
        // 检查是否成功读取响应数据
        if (data_read < 0)
        {
            // 如果读取失败，记录错误日志。
            ESP_LOGE(TAG, "Failed to read response");
            esp_http_client_close(client);
            success = false;
            goto http_cleanup;

        }

       if(success == true)
       {
            // 记录HTTP请求的状态码和内容长度
            ESP_LOGI(TAG, "HTTP GET Status = %d, content_length = %" PRId64,
                    esp_http_client_get_status_code(client),
                    esp_http_client_get_content_length(client));
                    
            // 记录HTTP响应的数据内容
            // %.*s 是一个格式说明符，用于以特定长度输出字符串。
            //ESP_LOGI(TAG, "Response Data: %.*s", data_read, output_buffer);

            // 调用 JSON 解析函数
            Intimate_weather = parse_weather_json(output_buffer);

            // 打印解析结果
            ESP_LOGI(TAG, "Weather Information:");
            ESP_LOGI(TAG, "Location: %s", Intimate_weather.location_name);
            ESP_LOGI(TAG, "Weather: %s", Intimate_weather.weather_text);
            ESP_LOGI(TAG, "Temperature: %d°C", Intimate_weather.temperature);
            ESP_LOGI(TAG, "Last Update: %s", Intimate_weather.last_update);
       }

http_cleanup:
        // 关闭HTTP客户端连接
        esp_http_client_close(client);
        // 等待一段时间后再次发起请求
        vTaskDelay(pdMS_TO_TICKS(3600000));
    }
}





